package myactest;

import component.MyDestructionAwareBeanPostProcessor;
import component.TestBeanDefinitionRegistryPostProcessor;
import component.TestJDKProxyInstantiationAwareBeanPostProcessor;
import config.ImportConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.TestBean;
import pojo.User;
import service.UserService;

/**
 * @author: ZhouBert
 * @date: 2020/8/28
 * @description:	实战测试 BeanDefinitionRegistryPostProcessor 的作用
 */
public class BeanDefinitionRegistryPostProcessorTest {


	@Test
	public void testMyBDRPostProcessor(){
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		//FirstConfig 有 ComponentScan
		//applicationContext.register(FirstConfig.class);
		applicationContext.register(ImportConfig.class);

		//测试循环 Import
		//applicationContext.register(MyConfig.class);

		applicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessor());

		//region	测试拓展点 InstantiationAwareBeanPostProcessor

		// 这个是来搞破坏的，因为类型不匹配了！
		//applicationContext.getBeanFactory().addBeanPostProcessor(new TestInstantiationAwareBeanPostProcessor());
		// 正常使用，比如使用 JDK 代理增强： TestJDKProxyInstantiationAwareBeanPostProcessor
		applicationContext.getBeanFactory().addBeanPostProcessor(new TestJDKProxyInstantiationAwareBeanPostProcessor());

		//endregion

		//为了让 TestBeanDefinitionRegistryPostProcessor 在方法中进行注册
		//applicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessorPriorityOrdered());
		applicationContext.refresh();

		//getBean
		User user = (User)applicationContext.getBean("component.MyFactoryBeanTestCache");
		System.out.println("user = " + user);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.login();

	}

	/**
	 * 测试 拓展点
	 * 可以断点在 AbstractApplicationContext 的 refresh() 方法中对 bean factory
	 * 中的 beanDefinitionMap 进行查看！
	 * 分析一波！
	 * 当添加了 MyInstanceSupplierBeanDefinitionRegistryPostProcessor 时：
	 * 由于 postProcessBeanDefinitionRegistry 方法中修改了 b.d. ,对 AppConfig 中的 userService 进行了覆盖！
	 * 所以，AppConfig 中的 @Bean userService 方法根本不会被调用！
	 *
	 * 当不添加 MyInstanceSupplierBeanDefinitionRegistryPostProcessor 时：
	 * 就会正常运行 @Bean 方法
	 * -----
	 * 具体的技术细节：
	 * loadBeanDefinitionsForBeanMethod 中的 isOverriddenByExistingDefinition() 判断：
	 * 如果不用 @Bean method 进行重写，就不生成 b.d. 进行注册！
	 *
	 * 这个 test case 也是 销毁方法的测试！！！
	 */
	@Test
	public void testInstanceSupplierTest(){
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(ImportConfig.class);

		// 比较 是否添加 MyInstanceSupplierBeanDefinitionRegistryPostProcessor 比较获取到的结果
		//applicationContext.addBeanFactoryPostProcessor(new MyInstanceSupplierBeanDefinitionRegistryPostProcessor());

		applicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessor());

		applicationContext.getBeanFactory().addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());

		applicationContext.refresh();
		UserService userDao = (UserService)applicationContext.getBean("userService");
		System.out.println(userDao);
		userDao = (UserService)applicationContext.getBean("userService");
		System.out.println(userDao);

		TestBean testBean = (TestBean) applicationContext.getBean("testBean");
		System.out.println("testBean = " + testBean);
		applicationContext.close();
	}

}
